package com.nn.service;

import com.nn.vo.ImageVO;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

@Service
@PropertySource("classpath:/image.properties")
public class FileServiceImpl implements FielService {
    //    使用配置文件动态的属性赋值!! @Value为属性赋值, 需要创建property文件
    @Value("${file.localDirPath}")
    private String localDirPath;    // = "C:/images";
    @Value("${file.preURLPath}")
    private String preURLPath;  // = "http://image.jt.com";

    /**
     * 1,校验上传的文件首先是 图片  .jpg .png .gif .jpeg 采用正则方式进行校验
     * 2.防止图片恶意攻击程序 验证是否有分辨率 像素(图片高度和宽度)
     * 3,文件分目录存储     例如:2021/11/11  hash码 8位 xx/xx/xx 数据hash时,因为是算法 可能造成数据分布不均
     * 4,防止文件重名,修改文件名称 UUID
     */
    @Override
    public ImageVO upload(MultipartFile file) {
        //1,校验图片类型是否正确  正则表达式
        //1.1,获取文件名称
        String filename = file.getOriginalFilename();
        //1.3,解决bug问题, 将名称全部小写
        filename = filename.toLowerCase();
        //1.2正则校验
        if (!filename.matches("^.+\\.(jpg|png|gif)$")) {
            //如果文件不是图片 则返回null
            return null;
        }
        //2,校验文件是否为恶意程序 通过图片对象 获取宽度和高度
        //2.1 将文件转换为图片对象
        try {
            BufferedImage bufferedImage = ImageIO.read(file.getInputStream());
            int height = bufferedImage.getHeight();
            int weight = bufferedImage.getWidth();
            if (height == 0 || weight == 0) {//短路或 只需要满足一个int=0
                return null;
            }
            //3,实现分目录存储--抽取其属性方便维护
            //3.1 按照时间将分配目录  /year/month/day
            String dateDirPath = new SimpleDateFormat("/yyyy/MM/dd/").format(new Date());
            //3.2 "C:/images/yyyy/MM/dd/" 目录
            String localDir = localDirPath + dateDirPath;
            File dirFile = new File(localDir);
            if (!dirFile.exists()) {//判断目录是否存在
                dirFile.mkdirs();//如目录不存在则创建目录
            }
            //4,防止文件重名,生成UUID  文件类型
            String uuid = UUID.randomUUID().toString().replace("-", "");
            //通过获取.的下标,拼接字符串
            int index = filename.lastIndexOf(".");
            String fileType = filename.substring(index); //根据给定的位置向后截取数据
            //获取文件名  .jpg
            String realFileName = uuid + fileType;
            //5,实现文件上传
            //5.1拼接文件全路径  目录/文件名称  --本地文件路径
            String localFilePath = localDir + realFileName;
            //5.2完成文件上传 transferTo
            file.transferTo(new File(localFilePath));
            /*
             * virtualPath--虚拟动态目录
             * C:\images\2021\07\13\9ea0d33064aa44d5abe2ec1231dc92d2.jpg
             * virtualPath-->\2021\07\13\9ea0d33064aa44d5abe2ec1231dc92d2.jpg
             * \2021\07\13\--->dateDirPath
             * 9ea0d33064aa44d5abe2ec1231dc92d2.jpg--->realFileName
             * */
            String virtualPath = dateDirPath + realFileName;
            //图片访问的网络路径 "http://image.jt.com/2021/07/13/9ea0d33064aa44d5abe2ec1231dc92d2.jpg"
            //真实的路径 "C:\images\2021\07\13\9ea0d33064aa44d5abe2ec1231dc92d2.jpg"
            String urlPath = preURLPath + virtualPath;
            ImageVO imageVO = new ImageVO(virtualPath, urlPath, realFileName);
            System.out.println(imageVO);
            return imageVO;
        } catch (IOException e) {
            e.printStackTrace();
            //终止程序
            return null;
        }
    }


    /**
     * 步骤:1,准备上传的目录
     *     2,获取文件上传的名称
     *     3,拼接文件路径
     *     4,实现文件上传
     *  关于业务层异常处理原则:将检查异常转化为运行异常*/
//    @Override
//    public void upload(MultipartFile file) {
//        String filePath="C:/images/";  //语法规范-C:\images-->C:/images
//        File fileDir = new File(filePath);
//        //判断目录是否存在
//        if (!fileDir.exists()){
//            //创建目录
//            fileDir.mkdirs();//创建多级目录
//        }
//        //获取文件名称
//        String fileName=file.getOriginalFilename();
//        //文件上传目录路径
//        String path=filePath+fileName;
//        //实现文件上传---try catch 解决异常
//        try {
//            file.transferTo(new File(path));
//        } catch (IOException e) {
//            e.printStackTrace();
//            throw new RuntimeException(e);//将检查异常转化为运行异常
//        }
//    }

    /**
     * 删除文件 1,准备文件的全路径 2,执行删除的操作
     */
    @Override
    public void deleteFile(String virtualPath) {
        // C:/images/yyyy/MM/dd/uuid.jpg
        String path = localDirPath + virtualPath;
        File file = new File(path);
        //实现文件删除操作
        file.delete();
    }
}
